package msc.ai.crypto.jade;

import java.io.Serializable;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;

import org.apache.commons.codec.binary.Hex;

public class CreditCard implements Serializable
{
	public static final int CC_STATE_ACTIVE = 1;
	public static final int CC_STATE_BLOCKED = 2;
	public static final int CC_STATE_EXPIRED = 3;
	public static final int CC_STATE_FRAUD = 4;
	
	private SecretKey key; // Key that unique for current object to do internal encrypting and decryption
	private String userName;
	private String addLine1;
	private String addLine2;
	private String addCity;
	private String addState;
	private String addZipCode;
	private String addCountry;	
	private String creditCardNo;
	private String creditCVVNo;
	private String creditCardType;	
	
	private String ccLimit;
	private String currentBalance;
	private String expireYear;
	private String expireMonth;
	private String ccStatus;
	
	
/*	private Double ccLimit; old version
	private Double currentBalance;
	private int expireYear;
	private int expireMonth;
	private int ccStatus;
	*/
	private String issuingBank;
	
	
	public CreditCard(String ccNumber, Double ccLimit, Double curBalance, int ccStatus)
	{
		try {
			key = KeyGenerator.getInstance("AES").generateKey(); // Unique for current object
		} catch (NoSuchAlgorithmException e) {
			
			
			e.printStackTrace();
		}
/*		this.creditCardNo = ccNumber;   old version
		this.ccLimit = ccLimit;
		this.currentBalance = curBalance;
		this.ccStatus = ccStatus;*/
		try{
		this.creditCardNo = getEncryptString(ccNumber);
		this.ccLimit = getEncryptString(new Double(ccLimit).toString());
		this.currentBalance = getEncryptString(new Double(curBalance).toString());
		this.ccStatus = getEncryptString(new Integer(ccStatus).toString());
		}catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	public 	boolean validateCCInfo(String ccNumber, String cvv,String type) throws NumberFormatException, Exception
	{
		if (getDecryptString(this.creditCardNo).equalsIgnoreCase(ccNumber) &&
				getDecryptString(this.creditCVVNo).equalsIgnoreCase(cvv) &&
				getDecryptString(this.creditCardType).equalsIgnoreCase(type) &&
				new Integer(	getDecryptString(this.ccStatus)).intValue() == CreditCard.CC_STATE_ACTIVE
				
				)
		{
			return true;
		}
		else
		{
			return false;
		}
		
	}
	
	public boolean doCCTxn(double txnAmt) throws  Exception
	{
		boolean txnState = false;
		synchronized (currentBalance)
		{
			if (txnAmt <= new Double(getDecryptString(this.currentBalance)).doubleValue() && txnAmt <= new Double(getDecryptString(this.ccLimit)).doubleValue())
			{
				double tempcurrentBalance= new Integer(getDecryptString(this.currentBalance)).intValue();
				tempcurrentBalance-= txnAmt;
				this.currentBalance= getEncryptString(new Double(tempcurrentBalance).toString());
				//this.currentBalance -= txnAmt; old version
				txnState = true;
			}
		}
		return txnState;
	}
	
	public boolean makePayment(double pmtAmt)
	{
		
		return false;
	}

	public String getUserName()
	{
		return userName;
	}

	public void setUserName(String userName) throws Exception
	{
		this.userName = getEncryptString(userName);
	}

	public String getAddLine1()
	{
		return addLine1;
	}

	public void setAddLine1(String addLine1) throws Exception
	{
		this.addLine1 = getEncryptString(addLine1);
	}

	public String getAddLine2()
	{
		return addLine2;
	}

	public void setAddLine2(String addLine2) throws Exception
	{
		this.addLine2 = getEncryptString(addLine2);
	}

	public String getAddCity()
	{
		return addCity;
	}

	public void setAddCity(String addCity) throws Exception
	{
		this.addCity = getEncryptString(addCity);
	}

	public String getAddState()
	{
		return addState;
	}

	public void setAddState(String addState) throws Exception
	{
		this.addState = getEncryptString(addState);
	}

	public String getAddZipCode()
	{
		return addZipCode;
	}

	public void setAddZipCode(String addZipCode) throws Exception
	{
		this.addZipCode = getEncryptString(addZipCode);
	}

	public String getAddCountry()
	{
		return addCountry;
	}

	public void setAddCountry(String addCountry) throws Exception
	{
		this.addCountry = getEncryptString(addCountry);
	}

	public String getCreditCardNo()
	{
		return creditCardNo;
	}

	public void setCreditCardNo(String creditCardNo) throws Exception
	{
		this.creditCardNo = getEncryptString(creditCardNo);
	}

	public String getCreditCVVNo()
	{
		return creditCVVNo;
	}

	public void setCreditCVVNo(String creditCVVNo) throws Exception
	{
		this.creditCVVNo = getEncryptString(creditCVVNo);
	}

	public String getCreditCardType()
	{
		return creditCardType;
	}

	public void setCreditCardType(String creditCardType) throws Exception
	{
		this.creditCardType = getEncryptString(creditCardType);
	}

	public String getCcLimit()//double
	{
		return ccLimit;
	}

	public void setCcLimit(double ccLimit) throws Exception
	{
		this.ccLimit = getEncryptString(new Double(ccLimit).toString());
	}

	public String getCurrentBalance()//double
	{
		return currentBalance;
	}

	public void setCurrentBalance(double currentBalance) throws Exception
	{
		this.currentBalance = getEncryptString( new Double(currentBalance).toString());
	}

	public String getExpireYear()
	{
		return expireYear;
	}

	public void setExpireYear(int expireYear) throws Exception
	{
		this.expireYear = getEncryptString(new Integer(expireYear).toString());
	}

	public String getExpireMonth()
	{
		return expireMonth;
	}

	public void setExpireMonth(int expireMonth) throws Exception
	{
		this.expireMonth = getEncryptString(new Integer(expireMonth).toString());
	}

	public String getCcStatus()
	{
		return ccStatus;
	}

	public void setCcStatus(int ccStatus) throws Exception
	{
		this.ccStatus = getEncryptString(new Integer(ccStatus).toString());
	}
	
	
	// Encrypt given Srting
	private String getEncryptString(String st)
			throws Exception {
//
//		Cipher cipher = Cipher.getInstance("AES");
//		cipher.init(Cipher.ENCRYPT_MODE, key);
//		byte[] enCardNO = cipher.doFinal(st.getBytes());
//		String enCardNO_st = new String(enCardNO);
//		return enCardNO_st;


		Cipher cipher = Cipher.getInstance("AES");
		cipher.init(Cipher.ENCRYPT_MODE, key);
		byte[] encrypted = cipher.doFinal(st.getBytes("UTF-8"));
		char[] encryptedTranspherable = Hex.encodeHex(encrypted);
		String enCardNO_st = new String(encryptedTranspherable);
		return enCardNO_st;
	
	
	}

	// Decrypt given String
	private String getDecryptString(String st)
			throws Exception {
//		
//		Cipher dcipher = Cipher.getInstance("AES");
//		dcipher.init(Cipher.DECRYPT_MODE, key);
//		byte[] recoveredBytes = dcipher.doFinal(st.getBytes());
//		return new String(recoveredBytes);


		Cipher dcipher = Cipher.getInstance("AES");
		dcipher.init(Cipher.DECRYPT_MODE, key);
		byte[] bts = Hex.decodeHex(st.toCharArray());
		
		byte[] recoveredBytes = dcipher.doFinal(bts);
	
		return new String(recoveredBytes,"UTF-8");
		
		
		
		
	}
	
	
	
}
